package com.framework.base.aqs;


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author chaolong.jin
 * @description
 * @date 2019/06/18 14:45
 */
public class LockTest {

    private static Lock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();
    private static volatile boolean flag = false;

    public static void main(String[] args) {

        A a = new A(1);
        A b = new A(2);
        a.start();
        b.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//        Integer i = 1;
//        Integer j = 2;
//        C c = new C(i, j);
//        D d = new D(i, j);
//        c.start();
//        d.start();
//        d.interrupt();
    }

    static class A extends Thread {
        private int flag;
        private Lock lock1 = new ReentrantLock();
        private Lock lock2 = new ReentrantLock();

        public A(int flag) {
            this.flag = flag;
        }

        @Override
        public void run() {
            try {
                if (flag == 1) {
                    lock1.lockInterruptibly();
                    Thread.sleep(500);
                    System.out.println( "1 running");
                    lock2.lockInterruptibly();
                } else {
                    lock2.lockInterruptibly();
                    Thread.sleep(500);
                    System.out.println( "2 running");
                    lock1.lockInterruptibly();

                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            finally {
                lock2.unlock();
                lock1.unlock();
            }


        }
    }

    static class B extends Thread {
        private Lock lock1;
        private Lock lock2;

        public B(Lock lock1, Lock lock2) {
            this.lock1 = lock1;
            this.lock2 = lock2;
        }

        @Override
        public void run() {
            try {
                lock2.lockInterruptibly();
                Thread.sleep(500);
                System.out.println(Thread.currentThread().getName() + "running");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock1.unlock();
            }

        }
    }

    static class C extends Thread {
        private Integer a;
        private Integer b;

        public C(Integer a, Integer b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public void run() {
            synchronized (a) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (b) {
                    System.out.println(Thread.currentThread().getName() + "running");
                }
            }
        }
    }

    static class D extends Thread {
        private Integer a;
        private Integer b;

        public D(Integer a, Integer b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public void run() {
            synchronized (b) {
                synchronized (a) {
                    System.out.println(Thread.currentThread().getName() + "running");
                }
            }
        }
    }

    static class ThreadSignal extends Thread {
        @Override
        public void run() {
            lock.lock();
            try {
                flag = true;
                System.out.println("signal");
                condition.signalAll();
            } finally {
                lock.unlock();
            }
        }
    }

    static class ThreadTest extends Thread {
        @Override
        public void run() {
            lock.lock();
            try {
                System.out.println("getLock");
                while (!flag) {
                    System.out.println(Thread.currentThread().getName() + " 不满足条件");
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + " sleep done");
            } finally {
                lock.unlock();
            }
        }
    }
}
